package com.dushuren.project.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dushuren.project.common.ErrorCode;
import com.dushuren.project.exception.BusinessException;
import com.dushuren.project.mapper.RecordWordsSearchMapper;
import com.dushuren.project.mapper.SuggestWordsSearchMapper;
import com.dushuren.project.model.entity.RecordWordsSearch;
import com.dushuren.project.model.entity.SuggestWordsSearch;
import com.dushuren.project.model.enums.SuggestSearchSelectEnum;
import com.dushuren.project.service.RecordWordsSearchService;
import com.dushuren.project.service.SuggestWordsSearchService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@Slf4j
public class QuerySearchWordsJob {


  @Resource
  RecordWordsSearchService recordWordsSearchService;

  @Resource
  RecordWordsSearchMapper recordWordsSearchMapper;


  @Resource
  SuggestWordsSearchService suggestWordsSearchService;


  @Resource
  SuggestWordsSearchMapper suggestWordsSearchMapper;

  @Resource
  RedissonClient redissonClient;

  /***
   * 常搜索词数据统计 数据统计
   *  每天晚上24点做一次数据统计
   */
  @Scheduled(cron = "0 0 0 * * ?")
  public void QuerySearch() {
	RLock lock = redissonClient.getLock("dushuren:seanrch:Query:lock");
	try {
	  // 只有一个线程获取锁
	  if (lock.tryLock(0, -1, TimeUnit.MICROSECONDS)) {
		log.info("QuerySearch Start");
		// 查询
		QueryWrapper<RecordWordsSearch> queryWrapper = new QueryWrapper<>();
		queryWrapper.select("id", "searchInformation");
		List<RecordWordsSearch> recordWordsSearches = recordWordsSearchMapper.selectList(queryWrapper);
		if (recordWordsSearches.isEmpty()) {
		  throw new BusinessException(ErrorCode.PARAMS_ERROR, "搜索数据不存在");
		}
		// 统计 List 的 information 的次数
		Map<String,Integer> recordCount = new HashMap<>();
		recordWordsSearches.stream().map(recordWordsSearch -> {
		  String searchInformation = recordWordsSearch.getSearchInformation();
		  recordCount.merge(searchInformation, 1, Integer::sum);
		  return 0;
		}).collect(Collectors.toList());
		// 删除已经统计出来的数据
		recordWordsSearchService.removeBatchByIds(recordWordsSearches);
		// 获取推荐表中的数据 Query
		QueryWrapper<SuggestWordsSearch> queryWrapperSuggest = new QueryWrapper<>();
		queryWrapperSuggest.select(SuggestSearchSelectEnum.getValues().toArray(new String[0]));
		for (String information: recordCount.keySet()) {
		  queryWrapperSuggest.eq(SuggestSearchSelectEnum.SEARCH_INFORMATION.getValue(), information).or();
		}
		List<SuggestWordsSearch> suggestWordsSearches = suggestWordsSearchMapper.selectList(queryWrapperSuggest);
		if (!suggestWordsSearches.isEmpty()) {
		  // 获取查询到已存在数的据 && 对数据进行修改
		  List<SuggestWordsSearch> suggestUpdateWordsSearches = suggestWordsSearches.stream().map(suggestWordsSearch -> {
			String searchInformation = suggestWordsSearch.getSearchInformation();
			Integer integer = recordCount.get(searchInformation);
			if (integer != null) {
			  Integer searchNumber = suggestWordsSearch.getSearchNumber();
			  suggestWordsSearch.setSearchNumber(searchNumber + integer);
			  recordCount.remove(searchInformation);
			}
			return suggestWordsSearch;
		  }).collect(Collectors.toList());
		  suggestWordsSearchService.updateBatchById(suggestUpdateWordsSearches);
		}
		// suggest 表中不存在数据，就行载入
		List<SuggestWordsSearch> collect = recordCount.keySet().stream().map(value -> {
		  SuggestWordsSearch suggestWordsSearch = new SuggestWordsSearch();
		  suggestWordsSearch.setSearchInformation(value);
		  suggestWordsSearch.setSearchNumber(recordCount.get(value));
		  return suggestWordsSearch;
		}).collect(Collectors.toList());
		suggestWordsSearchService.saveBatch(collect);
	  }

	} catch (InterruptedException e) {
	  log.error("redisson non-existent", e);
	} finally {
	  if (lock.isHeldByCurrentThread()) {
		lock.unlock();
	  }
	  log.info("QuerySearch end");
	}
  }
}